package vip.xiaonuo.biz.core.netty;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.json.XML;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import vip.xiaonuo.biz.core.cacheentity.Modules;
import vip.xiaonuo.biz.modular.facedata.entity.SFaceData;
import vip.xiaonuo.biz.modular.facedata.service.SFaceDataService;
import vip.xiaonuo.common.cache.CommonCacheOperator;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {

    private static CommonCacheOperator commonCacheOperator;

    private static SFaceDataService faceDataService;

    @Autowired
    public void setEmployeeServer(CommonCacheOperator commonCacheOperator, SFaceDataService faceDataService) {
        this.commonCacheOperator = commonCacheOperator;
        this.faceDataService = faceDataService;
    }


    /**
     * 从服务端收到新的数据时，这个方法会在收到消息时被调用
     *
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        String msgStr = msg.toString();
        try {
            if (msgStr.contains("FaceReaderAPI.Data.Classification")) {
                String xmlStr = msg.toString().split("FaceReaderAPI.Data.Classification")[1];
                String replace = xmlStr.replace("<?xml version=\"1.0\"?>\n" +
                        "<Classification xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", "");
                /*System.out.println(replace);*/
                JSONObject json;
                try {
                    json = XML.toJSONObject(replace);
                } catch (Exception e) {
                    return;
                }

                //System.out.println(json.toStringPretty());
                commonCacheOperator.put(Modules.FACE, Modules.ON);
                //System.out.println("face 在线");
                JSONObject classification = json.getJSONObject("Classification");
                if (classification.getStr("ClassificationValues").equals("")) {
                    Object o1 = commonCacheOperator.get("times");
                    long l = Long.parseLong(String.valueOf(o1));
                    commonCacheOperator.put("times", String.valueOf(l + 1));
                    if (l >= 50) {
                        if (String.valueOf(commonCacheOperator.get(Modules.FACEDEMOBILIZED)).equals("1")) {
                            //监测不到 人脸
                            Object o = commonCacheOperator.get(Modules.FACEDEMOBILIZEDTIMELIST);
                            JSONArray objects = JSONUtil.parseArray(o);
                            objects.add(String.valueOf(System.currentTimeMillis()));
                            int count = 0;
                            for (Object object : objects) {
                                if (System.currentTimeMillis() - Long.parseLong(String.valueOf(object)) <= 60000) {
                                    count++;
                                }
                            }
                            //min  离岗次数
                            commonCacheOperator.put(Modules.FACEDEMOBILIZEDTIME, count);
                            //System.out.println("-------------------" +System.currentTimeMillis());
                            commonCacheOperator.put(Modules.FACEDEMOBILIZEDCURRENTTIME, System.currentTimeMillis());
                            commonCacheOperator.put(Modules.FACEDEMOBILIZEDTIMELIST, objects);
                            commonCacheOperator.put(Modules.FACEDEMOBILIZED, Modules.OFF);
                        }
                    }

                    return;
                }
                Long time = classification.getLong("FrameTimeTicks");
                JSONObject classificationValues = classification.getJSONObject("ClassificationValues");
                JSONArray classificationValue = classificationValues.getJSONArray("ClassificationValue");
                toDb(classificationValue);
                Float nodFloat = 0F;
                Float yawnFloat = 0F;
                Float x1 = 0F;
                Float x2 = 0F;
                Float x3 = 0F;
                Float x4 = 0F;
                Float x5 = 0F;
                Float x6 = 0F;
                Float x7 = 0F;
                Float x8 = 0F;
                Float x9 = 0F;
                Float x10 = 0F;
                Float x11 = 0F;
                List<List<Float>> facePythonList = new ArrayList<>();
                List<Float>  faceOneList = new ArrayList<>();
                for (Object o : classificationValue) {
                    try{
                        faceOneList.add(JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float"));
                    }catch (Exception e){

                    }

                    if (JSONUtil.parseObj(o).get("Label").equals("俯仰角")) {
                        nodFloat = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                        x1 = nodFloat;
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 27 - 嘴唇张大延伸")) {
                        yawnFloat = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    /**
                     * 警觉性所需参数
                     */
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 01 - 右 - 内侧眉毛提起")) {
                        x2 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 01 - 左 - 内侧眉毛提起")) {
                        x3 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 07 - 右 - 眼睑收紧")) {
                        x4 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 07 - 左 - 眼睑收紧")) {
                        x5 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 02 - 左 - 外侧眉毛提起")) {
                        x6 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 02 - 右 - 外侧眉毛提起")) {
                        x7 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 23 - 绷紧嘴唇")) {
                        x8 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 20 - 嘴唇拉伸")) {
                        x9 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 24 - 紧压嘴唇")) {
                        x10 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }
                    if (JSONUtil.parseObj(o).get("Label").equals("动作单元 25 - 微张嘴唇")) {
                        x11 = JSONUtil.parseObj(o).getJSONObject("Value").getFloat("float");
                    }

                }
                facePythonList.add(faceOneList);
                commonCacheOperator.put("facePythonList", facePythonList);
                //System.out.println(json);
                //System.out.println(nodFloat + "  " + yawnFloat);
                face(nodFloat, yawnFloat, System.currentTimeMillis());
                faceAlarmResourct(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11);
                commonCacheOperator.put("times", "0");
                if (String.valueOf(commonCacheOperator.get(Modules.FACEDEMOBILIZED)).equals("0")) {
                    commonCacheOperator.put(Modules.FACEDEMOBILIZED, Modules.ON);
                    Object o = commonCacheOperator.get(Modules.FACEDEMOBILIZEDCURRENTTIME);
                    long l = Long.parseLong(String.valueOf(o));
                    //System.out.println("----------------" + System.currentTimeMillis() +"      "+l );
                    if (l == 0) {
                        return;
                    }
                    long DTime = System.currentTimeMillis() - l;
                    if (Long.parseLong(String.valueOf(commonCacheOperator.get(Modules.FACEDEMOBILIZEDMAX))) < DTime) {
                        commonCacheOperator.put(Modules.FACEDEMOBILIZEDMAX, String.format("%.2f", Double.parseDouble(String.valueOf(DTime)) / 1000D / 60D));
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            commonCacheOperator.put(Modules.FACE, Modules.OFF);
        }


       /* System.out.println("channelRead:read msg:"+msg.toString());
        byte[] bytes = hexStringToByteArray(msg);
        System.out.println("收到服务端十六进制消息: " + bytesToHexString(bytes));*/
        //回应服务端
        //ctx.write("I got server message thanks server!");
    }


    public void toDb(JSONArray classificationValue) {
        System.out.println(classificationValue);
        if (commonCacheOperator.get(Modules.CHECKSTATUS).equals(Modules.ON)) {
            SFaceData sFaceData = new SFaceData();
            sFaceData.setUserId(1L);
            sFaceData.setData(classificationValue.toString());
            sFaceData.setTime(System.currentTimeMillis());
            sFaceData.setCheckId(Integer.parseInt(commonCacheOperator.get(Modules.TASKID).toString()));
            sFaceData.setUserId(Long.parseLong(commonCacheOperator.get(Modules.USERID).toString()));

            faceDataService.save(sFaceData);
        }
    }

    /**
     * 从服务端收到新的数据、读取完成时调用
     *
     * @param ctx
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws IOException {
        //System.out.println("channelReadComplete");
        ctx.flush();
    }

    /**
     * 当出现 Throwable 对象才会被调用，即当 Netty 由于 IO 错误或者处理器在处理事件时抛出的异常时
     *
     * @param ctx
     * @param cause
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws IOException {
        System.out.println("exceptionCaught");
        cause.printStackTrace();
        ctx.close();//抛出异常，断开与客户端的连接
    }

    private static String startLog = "38 01 00 00 24 00 00 00 46 61 63 65 52 65 61 64 65 72 41 50 49 2E 4D 65 73 73 61 67 65 73 2E 41 63 74 69 6F 6E 4D 65 73 73 61 67 65 3C 3F 78 6D 6C 20 76 65 72 73 69 6F 6E 3D 22 31 2E 30 22 3F 3E 0D 0A 3C 41 63 74 69 6F 6E 4D 65 73 73 61 67 65 20 78 6D 6C 6E 73 3A 78 73 64 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 58 4D 4C 53 63 68 65 6D 61 22 20 78 6D 6C 6E 73 3A 78 73 69 3D 22 68 74 74 70 3A 2F 2F 77 77 77 2E 77 33 2E 6F 72 67 2F 32 30 30 31 2F 58 4D 4C 53 63 68 65 6D 61 2D 69 6E 73 74 61 6E 63 65 22 3E 0D 0A 20 20 3C 49 64 3E 36 64 35 63 35 36 38 37 2D 62 33 33 65 2D 34 34 66 34 2D 61 32 33 39 2D 30 62 63 30 32 36 33 34 61 39 31 32 3C 2F 49 64 3E 0D 0A 20 20 3C 41 63 74 69 6F 6E 54 79 70 65 3E 46 61 63 65 52 65 61 64 65 72 5F 53 74 61 72 74 5F 44 65 74 61 69 6C 65 64 4C 6F 67 53 65 6E 64 69 6E 67 3C 2F 41 63 74 69 6F 6E 54 79 70 65 3E 0D 0A 3C 2F 41 63 74 69 6F 6E 4D 65 73 73 61 67 65 3E";


    /**
     * 客户端与服务端第一次建立连接时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelActive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        System.out.println("channelActive:" + clientIp + ctx.name());
        ByteBuf message = null;
        ByteBuf buf1 = Unpooled.wrappedBuffer(hexStringToByteArray(startLog.replaceAll(" ", "")));
        ctx.writeAndFlush(buf1);
    }

    /**
     * 客户端与服务端 断连时 执行
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception, IOException {
        super.channelInactive(ctx);
        InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = insocket.getAddress().getHostAddress();
        ctx.close(); //断开连接时，必须关闭，否则造成资源浪费
        commonCacheOperator.put(Modules.FACE, Modules.OFF);
        System.out.println("channelInactive:" + clientIp);
    }


    private static String hexStringToString1(String hexString) {
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("输入的十六进制字符串长度不正确");
        }

        try {
            int byteArrayLength = hexString.length() / 2;
            byte[] byteArray = new byte[byteArrayLength];

            for (int i = 0; i < byteArrayLength; i++) {
                int index = i * 2;
                String hex = hexString.substring(index, index + 2);
                byte ascii = (byte) Integer.parseInt(hex, 16);
                byteArray[i] = ascii;
            }

            return new String(byteArray, "UTF-8");
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("输入的十六进制字符串包含非法字符");
        } catch (UnsupportedEncodingException e) {
            throw new IllegalStateException("不支持的字符编码");
        }
    }

    // 将十六进制字符串转换为字节数组
    private static byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        byte[] bytes = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            String subStr = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(subStr, 16);
        }
        return bytes;
    }

    // 将字节数组转换为十六进制字符串
    private static String bytesToHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    private int startNod = 0;
    private long startNodTime = 0;

    private int startYawn = 0;
    private long startYawnTime = 0;

    private List<Long> startYawnTimeList = new ArrayList<>();

    private List<Long> startNodTimeList = new ArrayList<>();

    /**
     * nod 点头
     * yawn 哈欠
     *
     * @param nodFloat
     * @param yawnFloat
     */
    private void face(Float nodFloat, Float yawnFloat, Long time) {
        Object yawnObj = commonCacheOperator.get(Modules.YAWNLIST);
        Object nodObj = commonCacheOperator.get(Modules.NODLIST);
        JSONArray nodArr = JSONUtil.parseArray(nodObj);
        JSONArray yawnArr = JSONUtil.parseArray(yawnObj);
        Object yawnlowObj = commonCacheOperator.get(Modules.YAWNLISTLOW);
        Object yawnhightObj = commonCacheOperator.get(Modules.YAWNLISTHIGHT);
        JSONArray startYawnTimeListLow = JSONUtil.parseArray(yawnlowObj);
        JSONArray startYawnTimeListHight = JSONUtil.parseArray(yawnhightObj);
        //System.out.println(nodFloat  + "   "  + time);
        //commonCacheOperator.put("had_had",nodFloat);
        //System.out.println(nodFloat);
        if (nodFloat <= -6F) {
            if (startNod == 0) {
                //开始点头
                startNod = 1;
                startNodTime = time;
            }
        } else {
            if (startNod == 1) {
                System.out.println("time - startNodTime:: " + (time - startNodTime));
                //150  3000 原来
                if ((time - startNodTime) >= 50 && (time - startNodTime) <= 3000) {
                    //记录为一次点头
                    nodArr.add(time);
                    System.out.println("点头一次");
                }
                //开始结束，
                startNod = 0;
                startNodTime = time;
            }
        }

        if (yawnFloat >= 0.50F) {
            if (startYawn == 0) {
                //开始哈欠
                startYawn = 1;
                startYawnTime = time;
            }
        } else {
            if (startYawn == 1) {
                //System.out.println("time - startNodTime" + (time - startYawnTime));
                if ((time - startYawnTime) >= 1500) {
                    //记录为一次哈欠
                    yawnArr.add(time);
                    System.out.println("哈欠一次");
                    if ((time - startYawnTime) >= 1500 && (time - startYawnTime) < 4000) {
                        //小哈欠
                        startYawnTimeListLow.add(time);
                    }
                    if ((time - startYawnTime) >= 4000) {
                        //大哈欠
                        startYawnTimeListHight.add(time);
                    }
                }
                //开始结束，
                startYawn = 0;
                startYawnTime = time;
            }
        }
        List<Long> timeOutLow = new ArrayList<>();
        for (Object object : startYawnTimeListLow) {
            long l = Long.parseLong(object.toString());
            System.out.println("L：" + l);
            System.out.println(time + " - 60000：" + (time - 60000));
            if (l <= time - 60000) {
                timeOutLow.add(l);
            }
        }
        for (Long l : timeOutLow) {
            startYawnTimeListLow.remove(l);
        }
        commonCacheOperator.put(Modules.YAWNLIST, startYawnTimeListLow);
        List<Long> timeOutHigjt = new ArrayList<>();
        for (Object object : startYawnTimeListHight) {
            long l = Long.parseLong(object.toString());
            System.out.println("L：" + l);
            System.out.println(time + " - 60000：" + (time - 60000));
            if (l <= time - 60000) {
                timeOutHigjt.add(l);
            }
        }
        for (Long l : timeOutHigjt) {
            startYawnTimeListHight.remove(l);
        }
        commonCacheOperator.put(Modules.YAWNLIST, startYawnTimeListHight);

        List<Long> timeOut = new ArrayList<>();
        for (Object object : yawnArr) {
            long l = Long.parseLong(object.toString());
            System.out.println("L：" + l);
            System.out.println(time + " - 60000：" + (time - 60000));
            if (l <= time - 60000) {
                timeOut.add(l);
            }
        }
        for (Long l : timeOut) {
            yawnArr.remove(l);
        }
        commonCacheOperator.put(Modules.YAWNLIST, yawnArr);


        List<Long> timeOut1 = new ArrayList<>();
        for (Object object : nodArr) {
            long l = Long.parseLong(object.toString());
            if (l <= time - 60000) {
                timeOut1.add(l);
            }
        }


        for (Long l : timeOut1) {
            nodArr.remove(l);
        }
        commonCacheOperator.put(Modules.NODLIST, nodArr);
       /* System.out.println("一分钟累计点头：" + nodArr.size());
        System.out.println("一分钟累计哈欠：" + yawnArr.size());*/
        commonCacheOperator.put(Modules.NODTIMERATE, nodArr.size());
        commonCacheOperator.put(Modules.YAWNTIMERATE, yawnArr.size());

    }

    /**
     * 警觉性得分
     */
    private void faceAlarmResourct(float x1, float x2, float x3, float x4, float x5, float x6, float x7, float x8, float x9, float x10, float x11) {
        Double resp = 78.233
                + (x1 * 4.574)
                + (x2 * 7.691)
                + (x3 * 74.943)
                + (x4 * 34.722)
                + (x5 * 130.630)
                + (x6 * -23.447)
                + (x7 * 44.582)
                + (x8 * 65.185)
                + (x9 * -58.446)
                + (x10 * -31.497)
                + (x11 * -24.277);
        if (resp <= 100 && resp >= 0) {
            commonCacheOperator.put(Modules.FACEALARMRESOURT, String.format("%.2f", resp));
        }

    }

}
